import java.util.Arrays;

/**
 * Computer Network, Programming Assignment #2
 * 
 * GP datagram definition.
 * @author Yancheng Li
 *
 */
public class GPDatagram {

	private int length;
	private int x;
	private int y;
	private int port;
	private char[] payload;
	private char[] rawdata;
	
	public GPDatagram(int x, int y, int port, char[] payload){
		this.length = payload.length + 16;
		this.x = x;
		this.y = y;
		this.port = port;
		this.payload = payload.clone();
		
		this.rawdata = new char[length];
		
		fill();
		
	}
	
	// Used for creating GPDatagrams with link length tables
	public GPDatagram(int x, int y, int port, char[] payload, int ignore){
		this.length = payload.length + 16;
		this.x = x;
		this.y = y;
		this.port = port;
		this.payload = payload.clone();
		
		this.rawdata = new char[length];
		fill();
		fillLinkLength();
	}
	
	public GPDatagram(char[] rawdata){
		this.rawdata = rawdata.clone();
		parse();
	}
	
	// fill the packet
	private void fill(){
		int base = 0;
		char[] numHex = Integer.toHexString(length).toCharArray();
		char[] digitNum = new char[4];
		
		//length
		for(int i = 0; i < 4; i++)
			digitNum[i] = '0';
		for(int i = numHex.length - 1, j = 3; i >= 0; i--, j--){
			digitNum[j] = numHex[i];
		}
		
		for(int i = 0; i < 4; i++)
			rawdata[base++] = digitNum[i];
		
		//x
		numHex = Integer.toHexString(x).toCharArray();
		for(int i = 0; i < 4; i++)
			digitNum[i] = '0';
		
		for(int i = numHex.length - 1, j = 3; i >= 0; i--, j--){
			digitNum[j] = numHex[i];
		}
		
		for(int i = 0; i < 4; i++)
			rawdata[base++] = digitNum[i];
		
		//y
		numHex = Integer.toHexString(y).toCharArray();
		for(int i = 0; i < 4; i++)
			digitNum[i] = '0';
		
		for(int i = numHex.length - 1, j = 3; i >= 0; i--, j--){
			digitNum[j] = numHex[i];
		}
		
		for(int i = 0; i < 4; i++)
			rawdata[base++] = digitNum[i];
		
		//port
		numHex = Integer.toHexString(port).toCharArray();
		
		for(int i = 0; i < 4; i++)
			digitNum[i] = '0';
		
		for(int i = numHex.length - 1, j = 3; i >= 0; i--, j--){
			digitNum[j] = numHex[i];
		}
		
		for(int i = 0; i < 4; i++)
			rawdata[base++] = digitNum[i];
		
		for(int i = 0; i < payload.length; i++)
			rawdata[base++] = payload[i];
		
	}
	
	// fill the packet for the Link Length
	private void fillLinkLength(){
		int base = 16;						
		
		int numEntries = (int)payload[0];
		
		char[] numHex = Integer.toHexString(payload[0]).toCharArray();
		char[] digitNum = new char[4];
		
		for (int i=0; i<4; i++){
			digitNum[i] = '0';				
		}
		
		for(int i = numHex.length - 1, j = 3; i >= 0; i--, j--){
			digitNum[j] = numHex[i];
		}
		
		for(int i = 0; i < 4; i++)
			rawdata[base++] = digitNum[i];
		
		// Fill in the gaps with the payload
		for (int m=0; m<numEntries; m++){
			for(int n=0; n<3; n++){
				numHex = Integer.toHexString(payload[m*3+n+1]).toCharArray();
				digitNum = new char[4];
			
				for (int i=0; i<4; i++){
					digitNum[i] = '0';				
				}
				
				for(int i = numHex.length - 1, j = 3; i >= 0; i--, j--){
					digitNum[j] = numHex[i];
				}
				
				for(int i = 0; i < 4; i++)
					rawdata[base++] = digitNum[i];
			}
		}
		//length
		/*for(int i = 0; i < 4; i++)
			digitNum[i] = '0';
		for(int i = numHex.length - 1, j = 3; i >= 0; i--, j--){
			digitNum[j] = numHex[i];
		}
		
		for(int i = 0; i < 4; i++)
			rawdata[base++] = digitNum[i];
		
		//x
		numHex = Integer.toHexString(x).toCharArray();
		for(int i = 0; i < 4; i++)
			digitNum[i] = '0';
		
		for(int i = numHex.length - 1, j = 3; i >= 0; i--, j--){
			digitNum[j] = numHex[i];
		}
		
		for(int i = 0; i < 4; i++)
			rawdata[base++] = digitNum[i];
		
		//y
		numHex = Integer.toHexString(y).toCharArray();
		for(int i = 0; i < 4; i++)
			digitNum[i] = '0';
		
		for(int i = numHex.length - 1, j = 3; i >= 0; i--, j--){
			digitNum[j] = numHex[i];
		}
		
		for(int i = 0; i < 4; i++)
			rawdata[base++] = digitNum[i];
		
		//port
		numHex = Integer.toHexString(port).toCharArray();
		
		for(int i = 0; i < 4; i++)
			digitNum[i] = '0';
		
		for(int i = numHex.length - 1, j = 3; i >= 0; i--, j--){
			digitNum[j] = numHex[i];
		}
		
		for(int i = 0; i < 4; i++)
			rawdata[base++] = digitNum[i];
		
		for(int i = 0; i < payload.length; i++)
			rawdata[base++] = payload[i];*/
		
	}
	// parse the packet
	private void parse(){
		int base = 0;
		char [] num = new char[4];
		
		for(int i = 0; i < 4; i++)
			num[i] = rawdata[base++];		
		length = Integer.parseInt(new String(num), 16);
		
		for(int i = 0; i < 4; i++)
			num[i] = rawdata[base++];		
		x = Integer.parseInt(new String(num), 16);
		
		for(int i = 0; i < 4; i++)
			num[i] = rawdata[base++];		
		y = Integer.parseInt(new String(num), 16);
		
		for(int i = 0; i < 4; i++)
			num[i] = rawdata[base++];		
		port = Integer.parseInt(new String(num), 16);
		
		payload = new char[length - 16];
		for(int i = 0; i < payload.length; i++)
			payload[i] = rawdata[base++];
		
		char[] tmpRawdata = new char[length];
		for(int i  = 0; i < length; i++)
			tmpRawdata[i] = rawdata[i];
		
		rawdata = tmpRawdata.clone();
		
		//fill();
		return;
		
	}

	public int getLength() {
		return length;
	}

	public void setLength(int length) {
		this.length = length;
	}

	public int getX() {
		return x;
	}

	public void setX(int x) {
		this.x = x;
	}

	public int getY() {
		return y;
	}

	public void setY(int y) {
		this.y = y;
	}

	public int getPort() {
		return port;
	}

	public void setPort(int port) {
		this.port = port;
	}

	public char[] getPayload() {
		return payload;
	}

	public void setPayload(char[] payload) {
		this.payload = payload;
	}

	public char[] getRawdata() {
		return rawdata;
	}

	public void setRawdata(char[] rawdata) {
		this.rawdata = rawdata;
	}

	@Override
	public String toString() {
		return "GPDatagram [length=" + length + ", payload="
				//+ Arrays.toString(payload) + ", port=" + port + ", rawdata="
				//+ Arrays.toString(rawdata) + ", x=" + x + ", y=" + y + "]";
				+ "[...]" + ", port=" + port + ", rawdata="
				+ "[...]" + ", x=" + x + ", y=" + y + "]";
	}
	
}
